package com.yunform.framework.hibernate;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.springframework.orm.ObjectRetrievalFailureException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class BaseHibernateDao<T extends BaseBean,PK extends Serializable> extends HibernateDaoSupport{
	
	private Class<T> persistentClass;
	
	public BaseHibernateDao(Class<T> entityClass){
		persistentClass = entityClass;
	}
	
	/**
	 * load object by id
	 */
	public T selectByPk(PK id) {
		T entity = super.getHibernateTemplate().get(persistentClass, id);
		
//		if (entity == null) {
//			throw new ObjectRetrievalFailureException(persistentClass, id);
//		}

		return entity;
	}
	
	/**
	 * load all objects
	 * @return
	 */
	public List<T> selectAll(){
		List<T> list = this.selectByParam(new QueryClause());
		this.getHibernateTemplate().clear();
		return list;
	}
	
	public List<T> selectByParam(final QueryClause queryClause){
//		if(! persistentClass.getName().equals("com.yunform.tenant.bean.Tenant")){
//			queryClause.andEqual("tenant", UserSessionFilter.getUser().getTenantId());
//		}
		
		/**
		 * 使用spring template 避免自己管理session
		 */
		return super.getHibernateTemplate().executeWithNativeSession(new HibernateCallback<List<T>>() {
			@SuppressWarnings("unchecked")
			public List<T> doInHibernate(Session session) throws HibernateException {
				Criteria criteria = session.createCriteria(persistentClass);
				for(Order order: queryClause.getOrders()){
					criteria.addOrder(order);
				}
				criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
				for(Criterion criterion : queryClause.getAndCriteria()){
					criteria.add(criterion);
				}
				return criteria.list();
			}
		});
		
		
	}
	
	public int deleteByParam(final QueryClause queryClause){
		return super.getHibernateTemplate().executeWithNativeSession(new HibernateCallback<Integer>() {
			@SuppressWarnings("unchecked")
			public Integer doInHibernate(Session session) throws HibernateException {
				Criteria criteria = session.createCriteria(persistentClass);
				criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
				for(Criterion criterion : queryClause.getAndCriteria()){
					criteria.add(criterion);
				}
				List<Object> obJList =  criteria.list();
				for(Object obj:obJList){
					session.delete(obj);
				}
				return obJList.size();
			}
		});
	}
	
	/**
	 * insert object
	 * @param object
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public PK insert(T object) {
		object.setCreateDate(new Date());
		
		PK pk = (PK)super.getHibernateTemplate().save(object);
		this.getHibernateTemplate().flush();
		this.getHibernateTemplate().clear();
		return pk;
	}
	
	/**
	 * update object
	 * @param object
	 */
	public void update(T object) {
		object.setModifyDate(new Date());
		
		super.getHibernateTemplate().update(object);
		this.getHibernateTemplate().flush();
		this.getHibernateTemplate().clear();
	}
	/**
	 * delete object by id
	 * @param id
	 */
	public void delete(PK id) {
		super.getHibernateTemplate().delete(this.selectByPk(id));
		this.getHibernateTemplate().flush();
		this.getHibernateTemplate().clear();
	}
	
	public void delete(T obj){
		super.getHibernateTemplate().delete(obj);
	}
	
	public void executeSQL(String sql){
		super.getSessionFactory().openSession().createSQLQuery(sql).executeUpdate();
	}
}
